vulkan: Fold clip into push constants
authorBenjamin Otte <otte@redhat.com>
Sat, 24 Dec 2016 03:58:51 +0000 (04:58 +0100)
committerBenjamin Otte <otte@redhat.com>
Sat, 24 Dec 2016 05:19:16 +0000 (06:19 +0100)
As a side effect, the clipping data is now available inside shaders.

Not that any shader would use them yet, but they could!

gsk/gskroundedrect.c
gsk/gskroundedrectprivate.h
gsk/gskvulkanclip.c
gsk/gskvulkanclipprivate.h
gsk/gskvulkanpushconstants.c
gsk/gskvulkanpushconstantsprivate.h
gsk/gskvulkanrenderpass.c
gsk/resources/vulkan/blit.vert.glsl
gsk/resources/vulkan/blit.vert.spv
gsk/resources/vulkan/color.vert.glsl
gsk/resources/vulkan/color.vert.spv

index 16ad85ef45284cc3b8f81d8b3695c972421b0cc1..03f987e964685207ed375538dc3fc143b6a3c520 100644 (file)
@@ -501,3 +501,33 @@ gsk_rounded_rect_path (const GskRoundedRect *self,
   cairo_close_path (cr);
 }
 
+/*
+ * Converts to the format we use in our shaders:
+ * vec4 rect;
+ * vec4 corner_widths;
+ * vec4 corner_heights;
+ * rect is (x, y, width, height), the corners are the same
+ * order as in the rounded rect.
+ *
+ * This is so that shaders can use just the first vec4 for
+ * rectilinear rects, the 2nd vec4 for circular rects and
+ * only look at the last vec4 if they have to.
+ */
+void
+gsk_rounded_rect_to_float (const GskRoundedRect *self,
+                           float                 rect[12])
+{
+  guint i;
+
+  rect[0] = self->bounds.origin.x;
+  rect[1] = self->bounds.origin.y;
+  rect[2] = self->bounds.size.width;
+  rect[3] = self->bounds.size.height;
+
+  for (i = 0; i < 4; i++)
+    {
+      rect[4 + i] = self->corner[i].width;
+      rect[8 + i] = self->corner[i].height;
+    }
+}
+
index d11567ad28521f3322e88e3299952a7e7bc8e930..5b40cb45bc564124c343a3e2dc321fa5a425f37d 100644 (file)
@@ -11,6 +11,8 @@ gboolean                 gsk_rounded_rect_is_circular           (const GskRounde
 
 void                     gsk_rounded_rect_path                  (const GskRoundedRect     *self,
                                                                  cairo_t                  *cr);
+void                     gsk_rounded_rect_to_float              (const GskRoundedRect     *self,
+                                                                 float                     rect[12]);
 
 G_END_DECLS
 
index 38755f5c2444f4d219a90e1e6fc23cc332af62c2..9a3ad8696f95cefa13552a71d3035d966b8beea6 100644 (file)
@@ -127,6 +127,34 @@ gsk_vulkan_clip_intersect_rounded_rect (GskVulkanClip        *dest,
   return TRUE;
 }
 
+gboolean
+gsk_vulkan_clip_transform (GskVulkanClip           *dest,
+                           const GskVulkanClip     *src,
+                           const graphene_matrix_t *transform,
+                           const graphene_rect_t   *viewport)
+{
+  switch (dest->type)
+    {
+    default:
+      g_assert_not_reached();
+      return FALSE;
+
+    case GSK_VULKAN_CLIP_ALL_CLIPPED:
+      gsk_vulkan_clip_init_copy (dest, src);
+      return TRUE;
+
+    case GSK_VULKAN_CLIP_NONE:
+      gsk_vulkan_clip_init_empty (dest, viewport);
+      return TRUE;
+
+    case GSK_VULKAN_CLIP_RECT:
+    case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR:
+    case GSK_VULKAN_CLIP_ROUNDED:
+      /* FIXME: Handle 2D operations, in particular transform and scale */
+      return FALSE;
+    }
+}
+
 gboolean
 gsk_vulkan_clip_contains_rect (const GskVulkanClip   *self,
                                const graphene_rect_t *rect)
index 492ef4c2b13efc98d691a9c020aa3d393ec3126f..99450afe4eed0bedcb065940340f394e0eaa795c 100644 (file)
@@ -44,6 +44,10 @@ gboolean                gsk_vulkan_clip_intersect_rect                  (GskVulk
 gboolean                gsk_vulkan_clip_intersect_rounded_rect          (GskVulkanClip          *dest,
                                                                          const GskVulkanClip    *src,
                                                                          const GskRoundedRect   *rounded) G_GNUC_WARN_UNUSED_RESULT;
+gboolean                gsk_vulkan_clip_transform                       (GskVulkanClip          *dest,
+                                                                         const GskVulkanClip    *src,
+                                                                         const graphene_matrix_t*transform,
+                                                                         const graphene_rect_t  *viewport) G_GNUC_WARN_UNUSED_RESULT;
 
 gboolean                gsk_vulkan_clip_contains_rect                   (const GskVulkanClip    *self,
                                                                          const graphene_rect_t  *rect) G_GNUC_WARN_UNUSED_RESULT;
index 4487687b6d30ac274f8b1966b05e38acc78c5159..f7daf1acbfab9c9394fc72917e5d80e7278ec760 100644 (file)
@@ -2,13 +2,15 @@
 
 #include "gskvulkanpushconstantsprivate.h"
 
-#include <math.h>
+#include "gskroundedrectprivate.h"
 
 void
 gsk_vulkan_push_constants_init (GskVulkanPushConstants  *constants,
-                                const graphene_matrix_t *mvp)
+                                const graphene_matrix_t *mvp,
+                                const graphene_rect_t   *viewport)
 {
   graphene_matrix_init_from_matrix (&constants->mvp, mvp);
+  gsk_vulkan_clip_init_empty (&constants->clip, viewport);
 }
 
 void
@@ -18,13 +20,42 @@ gsk_vulkan_push_constants_init_copy (GskVulkanPushConstants       *self,
   *self = *src;
 }
 
-void
-gsk_vulkan_push_constants_init_transform (GskVulkanPushConstants       *self,
-                                          const GskVulkanPushConstants *src,
-                                          const graphene_matrix_t      *transform)
+gboolean
+gsk_vulkan_push_constants_transform (GskVulkanPushConstants       *self,
+                                     const GskVulkanPushConstants *src,
+                                     const graphene_matrix_t      *transform,
+                                     const graphene_rect_t        *viewport)
 
 {
+  if (!gsk_vulkan_clip_transform (&self->clip, &src->clip, transform, viewport))
+    return FALSE;
+
   graphene_matrix_multiply (transform, &src->mvp, &self->mvp);
+  return TRUE;
+}
+
+gboolean
+gsk_vulkan_push_constants_intersect_rect (GskVulkanPushConstants       *self,
+                                          const GskVulkanPushConstants *src,
+                                          const graphene_rect_t        *rect)
+{
+  if (!gsk_vulkan_clip_intersect_rect (&self->clip, &src->clip, rect))
+    return FALSE;
+
+  graphene_matrix_init_from_matrix (&self->mvp, &src->mvp);
+  return TRUE;
+}
+
+gboolean
+gsk_vulkan_push_constants_intersect_rounded (GskVulkanPushConstants       *self,
+                                             const GskVulkanPushConstants *src,
+                                             const GskRoundedRect         *rect)
+{
+  if (!gsk_vulkan_clip_intersect_rounded_rect (&self->clip, &src->clip, rect))
+    return FALSE;
+
+  graphene_matrix_init_from_matrix (&self->mvp, &src->mvp);
+  return TRUE;
 }
 
 static void
@@ -32,6 +63,7 @@ gsk_vulkan_push_constants_wire_init (GskVulkanPushConstantsWire   *wire,
                                      const GskVulkanPushConstants *self)
 {
   graphene_matrix_to_float (&self->mvp, wire->vertex.mvp);
+  gsk_rounded_rect_to_float (&self->clip.rect, wire->vertex.clip);
 }
 
 void
index bdfd111d52d5eb1140b227fb9904392b3deab5b6..4642d526a3a8fca624b08d543d1e5f9a074a10d4 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <gdk/gdk.h>
 #include <graphene.h>
+#include <gsk/gskvulkanclipprivate.h>
 
 G_BEGIN_DECLS
 
@@ -12,12 +13,14 @@ typedef struct _GskVulkanPushConstantsWire GskVulkanPushConstantsWire;
 struct _GskVulkanPushConstants
 {
   graphene_matrix_t mvp;
+  GskVulkanClip clip;
 };
 
 struct _GskVulkanPushConstantsWire
 {
   struct {
     float mvp[16];
+    float clip[12];
   } vertex;
 #if 0
   struct {
@@ -30,12 +33,21 @@ const VkPushConstantRange *
 uint32_t                gst_vulkan_push_constants_get_range_count       (void) G_GNUC_PURE;
 
 void                    gsk_vulkan_push_constants_init                  (GskVulkanPushConstants         *constants,
-                                                                         const graphene_matrix_t        *mvp);
+                                                                         const graphene_matrix_t        *mvp,
+                                                                         const graphene_rect_t          *viewport);
 void                    gsk_vulkan_push_constants_init_copy             (GskVulkanPushConstants         *self,
                                                                          const GskVulkanPushConstants   *src);
-void                    gsk_vulkan_push_constants_init_transform        (GskVulkanPushConstants         *self,
+
+gboolean                gsk_vulkan_push_constants_transform             (GskVulkanPushConstants         *self,
+                                                                         const GskVulkanPushConstants   *src,
+                                                                         const graphene_matrix_t        *transform,
+                                                                         const graphene_rect_t          *viewport);
+gboolean                gsk_vulkan_push_constants_intersect_rect        (GskVulkanPushConstants         *self,
+                                                                         const GskVulkanPushConstants   *src,
+                                                                         const graphene_rect_t          *rect);
+gboolean                gsk_vulkan_push_constants_intersect_rounded     (GskVulkanPushConstants         *self,
                                                                          const GskVulkanPushConstants   *src,
-                                                                         const graphene_matrix_t        *transform);
+                                                                         const GskRoundedRect           *rect);
 
 void                    gsk_vulkan_push_constants_push_vertex           (const GskVulkanPushConstants   *self,
                                                                          VkCommandBuffer                 command_buffer,
index 796ba62ade856041e638aab0581b8f8972145e90..dc26f31f1c89a88e6a07c04bd2352f69ab0bbd59 100644 (file)
@@ -92,7 +92,6 @@ void
 gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
                                  GskVulkanRender               *render,
                                  const GskVulkanPushConstants  *constants,
-                                 const GskVulkanClip           *clip,
                                  GskRenderNode                 *node)
 {
   GskVulkanOp op = {
@@ -111,24 +110,24 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
     case GSK_CAIRO_NODE:
       if (gsk_cairo_node_get_surface (node) == NULL)
         return;
-      if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds))
-        FALLBACK ("Cairo nodes can't deal with clip type %u\n", clip->type);
+      if (!gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
+        FALLBACK ("Cairo nodes can't deal with clip type %u\n", constants->clip.type);
       op.type = GSK_VULKAN_OP_SURFACE;
       op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_BLIT);
       g_array_append_val (self->render_ops, op);
       return;
 
     case GSK_TEXTURE_NODE:
-      if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds))
-        FALLBACK ("Texture nodes can't deal with clip type %u\n", clip->type);
+      if (!gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
+        FALLBACK ("Texture nodes can't deal with clip type %u\n", constants->clip.type);
       op.type = GSK_VULKAN_OP_TEXTURE;
       op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_BLIT);
       g_array_append_val (self->render_ops, op);
       return;
 
     case GSK_COLOR_NODE:
-      if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds))
-        FALLBACK ("Color nodes can't deal with clip type %u\n", clip->type);
+      if (!gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
+        FALLBACK ("Color nodes can't deal with clip type %u\n", constants->clip.type);
       op.type = GSK_VULKAN_OP_COLOR;
       op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_COLOR);
       g_array_append_val (self->render_ops, op);
@@ -140,7 +139,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
 
         for (i = 0; i < gsk_container_node_get_n_children (node); i++)
           {
-            gsk_vulkan_render_pass_add_node (self, render, constants, clip, gsk_container_node_get_child (node, i));
+            gsk_vulkan_render_pass_add_node (self, render, constants, gsk_container_node_get_child (node, i));
           }
       }
       return;
@@ -148,21 +147,21 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
     case GSK_TRANSFORM_NODE:
       {
         graphene_matrix_t transform;
-        GskVulkanClip new_clip;
-        graphene_rect_t rect;
+        GskRenderNode *child;
 
+#if 0
         if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds))
           FALLBACK ("Transform nodes can't deal with clip type %u\n", clip->type);
+#endif
 
         gsk_transform_node_get_transform (node, &transform);
+        child = gsk_transform_node_get_child (node);
+        if (!gsk_vulkan_push_constants_transform (&op.constants.constants, constants, &transform, &child->bounds))
+          FALLBACK ("Transform nodes can't deal with clip type %u\n", constants->clip.type);
         op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS;
-        gsk_vulkan_push_constants_init_transform (&op.constants.constants, constants, &transform);
         g_array_append_val (self->render_ops, op);
 
-        graphene_matrix_transform_bounds (&transform, &clip->rect.bounds, &rect);
-        gsk_vulkan_clip_init_empty (&new_clip, &rect);
-
-        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &new_clip, gsk_transform_node_get_child (node));
+        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, child);
         gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants);
         g_array_append_val (self->render_ops, op);
       }
@@ -170,27 +169,37 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
 
     case GSK_CLIP_NODE:
       {
-        GskVulkanClip new_clip;
-
-        if (!gsk_vulkan_clip_intersect_rect (&new_clip, clip, gsk_clip_node_peek_clip (node)))
-          FALLBACK ("Failed to find intersection between clip of type %u and rectangle\n", clip->type);
-        if (new_clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED)
+        if (!gsk_vulkan_push_constants_intersect_rect (&op.constants.constants, constants, gsk_clip_node_peek_clip (node)))
+          FALLBACK ("Failed to find intersection between clip of type %u and rectangle\n", constants->clip.type);
+        if (&op.constants.constants.clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED)
           return;
 
-        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &new_clip, gsk_clip_node_get_child (node));
+        op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS;
+        g_array_append_val (self->render_ops, op);
+
+        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, gsk_clip_node_get_child (node));
+
+        gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants);
+        g_array_append_val (self->render_ops, op);
       }
       return;
 
     case GSK_ROUNDED_CLIP_NODE:
       {
-        GskVulkanClip new_clip;
-
-        if (!gsk_vulkan_clip_intersect_rounded_rect (&new_clip, clip, gsk_rounded_clip_node_peek_clip (node)))
-          FALLBACK ("Failed to find intersection between clip of type %u and rounded rectangle\n", clip->type);
-        if (new_clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED)
+        if (!gsk_vulkan_push_constants_intersect_rounded (&op.constants.constants,
+                                                          constants,
+                                                          gsk_rounded_clip_node_peek_clip (node)))
+          FALLBACK ("Failed to find intersection between clip of type %u and rounded rectangle\n", constants->clip.type);
+        if (&op.constants.constants.clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED)
           return;
 
-        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &new_clip, gsk_rounded_clip_node_get_child (node));
+        op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS;
+        g_array_append_val (self->render_ops, op);
+
+        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, gsk_rounded_clip_node_get_child (node));
+
+        gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants);
+        g_array_append_val (self->render_ops, op);
       }
       return;
     }
@@ -199,19 +208,19 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
   return;
 
 fallback:
-  switch (clip->type)
+  switch (constants->clip.type)
     {
       case GSK_VULKAN_CLIP_NONE:
         op.type = GSK_VULKAN_OP_FALLBACK;
         break;
       case GSK_VULKAN_CLIP_RECT:
         op.type = GSK_VULKAN_OP_FALLBACK_CLIP;
-        gsk_rounded_rect_init_copy (&op.render.clip, &clip->rect);
+        gsk_rounded_rect_init_copy (&op.render.clip, &constants->clip.rect);
         break;
       case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR:
       case GSK_VULKAN_CLIP_ROUNDED:
         op.type = GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP;
-        gsk_rounded_rect_init_copy (&op.render.clip, &clip->rect);
+        gsk_rounded_rect_init_copy (&op.render.clip, &constants->clip.rect);
         break;
       case GSK_VULKAN_CLIP_ALL_CLIPPED:
       default:
@@ -231,15 +240,12 @@ gsk_vulkan_render_pass_add (GskVulkanRenderPass     *self,
                             GskRenderNode           *node)
 {
   GskVulkanOp op = { 0, };
-  GskVulkanClip clip;
 
   op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS;
-  gsk_vulkan_push_constants_init (&op.constants.constants, mvp);
+  gsk_vulkan_push_constants_init (&op.constants.constants, mvp, viewport);
   g_array_append_val (self->render_ops, op);
 
-  gsk_vulkan_clip_init_empty (&clip, viewport);
-
-  gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &clip, node);
+  gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, node);
 }
 
 static void
index 2522b7e0ef4eaba4ed5ddbbc551cfbb85d77999e..ca78688909e7bb743ce8e3bd9824747b14b1adb2 100644 (file)
@@ -5,6 +5,9 @@ layout(location = 1) in vec2 inTexCoord;
 
 layout(push_constant) uniform PushConstants {
     mat4 mvp;
+    vec4 clip_bounds;
+    vec4 clip_widths;
+    vec4 clip_heights;
 } push;
 
 layout(location = 0) out vec2 outTexCoord;
index 3deee1c8e2a792b01265279178a88a50f7f957a9..5ce7a27f299d212c57410b93e25ed802715369af 100644 (file)
Binary files a/gsk/resources/vulkan/blit.vert.spv and b/gsk/resources/vulkan/blit.vert.spv differ
index 78bbfe12831c725318d3e31936f369181c8e0595..873ccfc949c86667836c56bf04907522a2d05609 100644 (file)
@@ -5,6 +5,9 @@ layout(location = 1) in vec4 inColor;
 
 layout(push_constant) uniform PushConstants {
     mat4 mvp;
+    vec4 clip_bounds;
+    vec4 clip_widths;
+    vec4 clip_heights;
 } push;
 
 layout(location = 0) out vec4 outColor;
index f4a8791bd700d26a4f3f2bbd69d5f0c99d8e31a5..0d571efc35ac80388d10181e672c6516dcc42641 100644 (file)
Binary files a/gsk/resources/vulkan/color.vert.spv and b/gsk/resources/vulkan/color.vert.spv differ